/*
 * Copyright (C) 2009 M. Hautle.
 * 
 * This file is part of TrackedBean.
 * 
 * TrackedBean is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * TrackedBean is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with TrackedBean. If not, see <http://www.gnu.org/licenses/>.
 */
package ch.trackedbean.binding.mapping;

import org.jdesktop.beansbinding.*;

/**
 * Class holding infomations for a {@link Binding}.
 * 
 * @author M. Hautle
 */
@SuppressWarnings("unchecked")
public class BindingInfos {
	/** Represents an undefined value. */
	protected static final Object UNDEFINED = new Object();

	/** The name of the property */
	protected final String property;

	/** The converter to use or null */
	protected Converter converter;

	/** The source null value to use or null */
	protected Object sourceNullValue;

	/** The source unreadable value to use, {@link #UNDEFINED} or null */
	protected Object sourceUnreadableValue = UNDEFINED;

	/** The target null value to use or null */
	protected Object targetNullValue;

	/** The validator to use or null */
	protected Validator validator;

	/** A sub/related binding or null. */
	protected ISubBinding subBinding;

	/**
	 * Default constructor
	 * 
	 * @param property The name of the property
	 */
	public BindingInfos(final String property) {
		this.property = property;
	}

	/**
	 * Default constructor
	 * 
	 * @param property The name of the property
	 * @param converter The converter to use
	 * @param sourceNullValue The source null value
	 * @param sourceUnreadableValue The source unreadable value
	 * @param targetNullValue The target null value
	 * @param validator The validator
	 */
	public BindingInfos(final String property, final Converter converter, final Object sourceNullValue, final Object sourceUnreadableValue,
			final Object targetNullValue, final Validator validator) {
		this.property = property;
		this.converter = converter;
		this.sourceNullValue = sourceNullValue;
		this.sourceUnreadableValue = sourceUnreadableValue;
		this.targetNullValue = targetNullValue;
		this.validator = validator;
	}

	/**
	 * Returns the converter for this binding.
	 * 
	 * @return the converter
	 */
	public Converter getConverter() {
		return converter;
	}

	/**
	 * Sets the converter for this binding.
	 * 
	 * @param converter the converter to set, may be <code>null</code>
	 */
	public void setConverter(final Converter converter) {
		this.converter = converter;
	}

	/**
	 * Sets the value representing <code>null</code> in the source.
	 * 
	 * @return the sourceNullValue
	 */
	public Object getSourceNullValue() {
		return sourceNullValue;
	}

	/**
	 * Returns the value representing <code>null</code> in the source.
	 * 
	 * @param sourceNullValue the sourceNullValue to set, may be <code>null</code>
	 */
	public void setSourceNullValue(final Object sourceNullValue) {
		this.sourceNullValue = sourceNullValue;
	}

	/**
	 * Clears the value of {@link #sourceUnreadableValue} to undefined.
	 */
	public void unsetSourceUnreadableValue() {
		sourceUnreadableValue = UNDEFINED;
	}

	/**
	 * Returns the value representing an unreadable source.
	 * 
	 * @return the sourceUnreadableValue
	 */
	public Object getSourceUnreadableValue() {
		return sourceUnreadableValue;
	}

	/**
	 * Sets the value representing an unreadable source.
	 * 
	 * @param sourceUnreadableValue the sourceUnreadableValue to set, may be <code>null</code>
	 */
	public void setSourceUnreadableValue(final Object sourceUnreadableValue) {
		this.sourceUnreadableValue = sourceUnreadableValue;
	}

	/**
	 * Returns the value representing <code>null</code> in the target.
	 * 
	 * @return the targetNullValue
	 */
	public Object getTargetNullValue() {
		return targetNullValue;
	}

	/**
	 * Sets the value representing <code>null</code> in the target.
	 * 
	 * @param targetNullValue the targetNullValue to set, may be <code>null</code>
	 */
	public void setTargetNullValue(final Object targetNullValue) {
		this.targetNullValue = targetNullValue;
	}

	/**
	 * Sets the validator of this binding.
	 * 
	 * @return the validator
	 */
	public Validator getValidator() {
		return validator;
	}

	/**
	 * Returns the validator of this binding.
	 * 
	 * @param validator the validator to set, may be <code>null</code>
	 */
	public void setValidator(final Validator validator) {
		this.validator = validator;
	}

	/**
	 * Returns the sub binding.
	 * 
	 * @return the subbinding or null
	 */
	public ISubBinding getSubBinding() {
		return subBinding;
	}

	/**
	 * Sets the subbinding.
	 * 
	 * @param subBinding The subBinding to set, may be <code>null</code>
	 */
	public void setSubBinding(ISubBinding subBinding) {
		this.subBinding = subBinding;
	}

	/**
	 * Returns the source property of this binding.
	 * 
	 * @return the property
	 */
	public String getProperty() {
		return property;
	}

	/**
	 * Configures the binding according to the values in this Info Bean.<br>
	 * If a value in this Bean is null, then the property in the binding won't be touched.
	 * 
	 * @param binding The binding to configure
	 */
	void configure(final Binding binding) {
		binding.setConverter(converter);
		binding.setSourceNullValue(sourceNullValue);
		binding.setTargetNullValue(targetNullValue);
		binding.setValidator(validator);
		if (sourceUnreadableValue == UNDEFINED)
			binding.unsetSourceUnreadableValue();
		else
			binding.setSourceUnreadableValue(sourceUnreadableValue);
	}

	/**
	 * Bind the subBinding if one exists.
	 */
	void bindSubBinding() {
		if (subBinding != null)
			subBinding.bind(this);
	}

	/**
	 * Unbind the subBinding if one exists.
	 */
	void unbindSubBinding() {
		if (subBinding != null)
			subBinding.unbind(this);
	}
}
